package com.hdmp.auth.configuration;

import com.google.common.collect.Maps;
import com.hdmp.auth.cache.SpringCacheManagerWrapper;
import com.hdmp.auth.shiro.*;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;

/**
 * @author BigFan
 * @create 2018/11/14 7:28 PM
 */
@Configuration
public class ShiroConfig {

    /**
     * 定义sessionManager bean
     *
     * @return
     */
    @Bean("sessionManager")
    public SessionManager sessionManager() {
        JavaUuidSessionIdGenerator sessionIdGenerator = new JavaUuidSessionIdGenerator();
        SimpleCookie sessionIdCookie = new SimpleCookie("sid");
        sessionIdCookie.setHttpOnly(true);
        sessionIdCookie.setMaxAge(-1);

        EnterpriseCacheSessionDAO sessionDAO = new EnterpriseCacheSessionDAO();
        sessionDAO.setActiveSessionsCacheName("shiro-activeSessionCache");
        sessionDAO.setSessionIdGenerator(sessionIdGenerator);
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setGlobalSessionTimeout(30 * 60 * 1000);
        sessionManager.setDeleteInvalidSessions(true);
        sessionManager.setSessionValidationSchedulerEnabled(true);
        sessionManager.setSessionIdCookieEnabled(true);
        sessionManager.setSessionDAO(sessionDAO);
        sessionManager.setSessionValidationInterval(20 * 1000);
        sessionManager.setSessionIdCookie(sessionIdCookie);
        sessionManager.setSessionIdCookieEnabled(true);
        return sessionManager;
    }

    @Bean
    public SecurityManager securityManager(UserRealm userRealm, SessionManager sessionManager
            , EhCacheCacheManager ehCacheCacheManager) {
        SpringCacheManagerWrapper springCacheManagerWrapper = new SpringCacheManagerWrapper();
        springCacheManagerWrapper.setCacheManager(ehCacheCacheManager);
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm);
        securityManager.setSessionManager(sessionManager);
        securityManager.setCacheManager(springCacheManagerWrapper);
        return securityManager;

    }


    /**
     * 定义扩展的 formAuthenticationFilter
     * 定义为异步返回形式
     *
     * @return
     */
    @Bean
    public FormAuthenticationFilter formAuthenticationFilter() {
/*        FormAuthenticationFilter formAuthenticationFilter = new FormAuthenticationExtendFilter();
        formAuthenticationFilter.setLoginUrl("/login");
        formAuthenticationFilter.setUsernameParam("username");
        formAuthenticationFilter.setPasswordParam("password");
        formAuthenticationFilter.setSuccessUrl("/test");*/

        FormAuthenticationFilter formAuthenticationFilter = new FormAuthenticationFilter();
        formAuthenticationFilter.setLoginUrl("/login");
        formAuthenticationFilter.setSuccessUrl("/loginSuccess");
        formAuthenticationFilter.setUsernameParam("username");
        formAuthenticationFilter.setPasswordParam("password");

        return formAuthenticationFilter;
    }

    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager, FormAuthenticationFilter formAuthenticationFilter,
                                                         WechatFilter wechatFilter, SysUserFilter sysUserFilter) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl("/login");
        shiroFilterFactoryBean.setSuccessUrl("/loginSuccess");
        Map<String, Filter> filters = new HashMap<>();
        filters.put("auth", formAuthenticationFilter);
        filters.put("wechat", wechatFilter);
        filters.put("sysUser", sysUserFilter);
        shiroFilterFactoryBean.setFilters(filters);

        Map<String, String> filterLinkMap = Maps.newLinkedHashMap();
        filterLinkMap.put("/activiti/**", "anon");
        filterLinkMap.put("/image/**", "anon");
        filterLinkMap.put("/swagger/**", "anon");
        filterLinkMap.put("/swagger-ui.html", "anon");
        filterLinkMap.put("/webjars/**", "anon");
        filterLinkMap.put("/swagger-resources/**", "anon");
        filterLinkMap.put("/wechat/**", "anon");
        filterLinkMap.put("/MP_verify_XOE5ijn8CpE6cYHx.txt", "anon");
        filterLinkMap.put("/MP_verify_5ZcDBgfP6diW75lg.txt", "anon");
        filterLinkMap.put("/libiary/**", "wechat");
        filterLinkMap.put("/**", "sysUser");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterLinkMap);
        return shiroFilterFactoryBean;

    }

    @Bean
    public WechatFilter weworkFilter(){
        return new WechatFilter();
    }
    @Bean
    public SysUserFilter sysUserFilter(){
        return new SysUserFilter();
    }

    @Bean
    public UserRealm userRealm(EhCacheCacheManager ehCacheCacheManager) {
        RetryLimitHashedCredentialsMatcher retryLimitHashedCredentialsMatcher =
                new RetryLimitHashedCredentialsMatcher();
        retryLimitHashedCredentialsMatcher.setEhCacheCacheManager(ehCacheCacheManager);
        retryLimitHashedCredentialsMatcher.setHashIterations(2);
        retryLimitHashedCredentialsMatcher.setHashAlgorithmName("MD5");
        retryLimitHashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);

        UserRealm userRealm = new UserRealm();
        userRealm.setCredentialsMatcher(retryLimitHashedCredentialsMatcher);
        userRealm.setCachingEnabled(false);
        return userRealm;
    }


    /**
     * 处理shiro 生命周期使用
     *
     * @return
     */
    @Bean("lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     * AOP式方法级权限检查
     *
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
        proxyCreator.setProxyTargetClass(true);
        return proxyCreator;
    }

    /**
     * 配置shiro 支持权限控制
     *
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
}
